import { PlayerAppService } from '../service/PlayerAppService';
import { PlayerRepository, PlayerRepositoryImpl } from '../repository/PlayerRepository';
import { PlayerDataSource, MockPlayerDataSource } from '../data/datasource/PlayerDataSource';
import { PlayerAggregate } from '../domain/aggregate/PlayerAggregate';
import { PlayerEntity } from '../domain/entity/PlayerEntity';

export class PlayerModuleTester {
  private playerService: PlayerAppService = PlayerAppService.getInstance();
  private testResults: { testName: string; success: boolean; message: string }[] = [];
  
  // 执行所有测试
  async runAllTests(): Promise<void> {
    console.log('====== 开始测试玩家模块 ======');
    
    await this.testPlayerRegistration();
    await this.testPlayerLogin();
    await this.testPlayerDataUpdate();
    await this.testCaseCompletion();
    await this.testAchievementUnlocking();
    await this.testPlayerStatistics();
    await this.testLeaderboard();
    
    this.printTestSummary();
  }
  
  // 测试玩家注册
  private async testPlayerRegistration(): Promise<void> {
    const testName = '玩家注册测试';
    try {
      console.log(`[测试中] ${testName}`);
      
      // 使用时间戳生成唯一用户名
      const uniqueUsername = `test_user_${Date.now()}`;
      const nickname = '测试玩家';
      
      const player = await this.playerService.registerPlayer(
        uniqueUsername,
        nickname
      );
      
      if (player && player.username === uniqueUsername && player.nickname === nickname) {
        this.addTestResult(testName, true, '玩家注册成功');
        console.log(`✅ ${testName}: 成功`);
      } else {
        this.addTestResult(testName, false, '注册返回的玩家信息不匹配');
        console.log(`❌ ${testName}: 失败 - 返回的玩家信息不匹配`);
      }
    } catch (error) {
      this.addTestResult(testName, false, `注册过程发生错误: ${error}`);
      console.log(`❌ ${testName}: 失败 - ${error}`);
    }
  }
  
  // 测试玩家登录
  private async testPlayerLogin(): Promise<void> {
    const testName = '玩家登录测试';
    try {
      console.log(`[测试中] ${testName}`);
      
      // 先注册一个测试账号
      const uniqueUsername = `login_test_user_${Date.now()}`;
      const nickname = '登录测试玩家';
      
      const registeredPlayer = await this.playerService.registerPlayer(
        uniqueUsername,
        nickname
      );
      
      if (!registeredPlayer) {
        this.addTestResult(testName, false, '注册失败，无法进行登录测试');
        console.log(`❌ ${testName}: 失败 - 注册失败`);
        return;
      }
      
      // 测试登录
      const loggedInPlayer = await this.playerService.loginPlayer(uniqueUsername);
      
      if (loggedInPlayer && loggedInPlayer.id === registeredPlayer.id) {
        this.addTestResult(testName, true, '玩家登录成功');
        console.log(`✅ ${testName}: 成功`);
      } else {
        this.addTestResult(testName, false, '登录返回的玩家信息不匹配');
        console.log(`❌ ${testName}: 失败 - 登录返回的玩家信息不匹配`);
      }
    } catch (error) {
      this.addTestResult(testName, false, `登录过程发生错误: ${error}`);
      console.log(`❌ ${testName}: 失败 - ${error}`);
    }
  }
  
  // 测试玩家数据更新
  private async testPlayerDataUpdate(): Promise<void> {
    const testName = '玩家数据更新测试';
    try {
      console.log(`[测试中] ${testName}`);
      
      // 创建测试玩家
      const player = await this.playerService.registerPlayer(
        `update_test_user_${Date.now()}`,
        '初始昵称'
      );
      
      if (!player) {
        this.addTestResult(testName, false, '注册失败，无法进行更新测试');
        console.log(`❌ ${testName}: 失败 - 注册失败`);
        return;
      }
      
      // 更新玩家信息
      const newNickname = '更新后的昵称';
      const updateSuccess = await this.playerService.updatePlayerInfo(
        player.id,
        { nickname: newNickname }
      );
      
      if (updateSuccess) {
        // 验证更新结果
        const updatedPlayer = await this.playerService.getPlayerById(player.id);
        if (updatedPlayer && updatedPlayer.playerEntity.nickname === newNickname) {
          this.addTestResult(testName, true, '玩家数据更新成功');
          console.log(`✅ ${testName}: 成功`);
        } else {
          this.addTestResult(testName, false, '更新后的玩家信息不匹配');
          console.log(`❌ ${testName}: 失败 - 更新后的玩家信息不匹配`);
        }
      } else {
        this.addTestResult(testName, false, '更新操作返回失败');
        console.log(`❌ ${testName}: 失败 - 更新操作返回失败`);
      }
    } catch (error) {
      this.addTestResult(testName, false, `更新过程发生错误: ${error}`);
      console.log(`❌ ${testName}: 失败 - ${error}`);
    }
  }
  
  // 测试案件完成功能
  private async testCaseCompletion(): Promise<void> {
    const testName = '案件完成功能测试';
    try {
      console.log(`[测试中] ${testName}`);
      
      const player = await this.playerService.registerPlayer(
        `case_test_user_${Date.now()}`,
        '案件测试玩家'
      );
      
      if (!player) {
        this.addTestResult(testName, false, '注册失败，无法进行案件完成测试');
        console.log(`❌ ${testName}: 失败 - 注册失败`);
        return;
      }
      
      // 测试成功破案
      const statistics = await this.playerService.completeCase(
        player.id,
        'case_001',
        true, // 正确破案
        3,    // 难度：中
        300,  // 耗时：300秒
        true  // 首次尝试
      );
      
      if (statistics && statistics.solvedCases > 0) {
        this.addTestResult(testName, true, '案件完成功能测试成功');
        console.log(`✅ ${testName}: 成功`);
      } else {
        this.addTestResult(testName, false, '案件完成后统计数据未更新');
        console.log(`❌ ${testName}: 失败 - 统计数据未更新`);
      }
    } catch (error) {
      this.addTestResult(testName, false, `案件完成过程发生错误: ${error}`);
      console.log(`❌ ${testName}: 失败 - ${error}`);
    }
  }
  
  // 测试成就解锁
  private async testAchievementUnlocking(): Promise<void> {
    const testName = '成就解锁测试';
    try {
      console.log(`[测试中] ${testName}`);
      
      const player = await this.playerService.registerPlayer(
        `achievement_test_user_${Date.now()}`,
        '成就测试玩家'
      );
      
      if (!player) {
        this.addTestResult(testName, false, '注册失败，无法进行成就解锁测试');
        console.log(`❌ ${testName}: 失败 - 注册失败`);
        return;
      }
      
      // 连续破案解锁第一个成就
      let hasAchievement = false;
      
      for (let i = 0; i < 3; i++) {
        await this.playerService.completeCase(
          player.id,
          `case_achievement_${i}`,
          true,
          1,
          120,
          true
        );
      }
      
      // 获取更新后的玩家信息
      const updatedPlayer = await this.playerService.getPlayerById(player.id);
      
      if (updatedPlayer && updatedPlayer.achievements.length > 0) {
        hasAchievement = updatedPlayer.achievements.some(a => a.isUnlocked);
      }
      
      if (hasAchievement) {
        this.addTestResult(testName, true, '成就解锁测试成功');
        console.log(`✅ ${testName}: 成功`);
      } else {
        this.addTestResult(testName, false, '未成功解锁成就');
        console.log(`❌ ${testName}: 失败 - 未解锁成就`);
      }
    } catch (error) {
      this.addTestResult(testName, false, `成就解锁过程发生错误: ${error}`);
      console.log(`❌ ${testName}: 失败 - ${error}`);
    }
  }
  
  // 测试统计功能
  private async testPlayerStatistics(): Promise<void> {
    const testName = '玩家统计功能测试';
    try {
      console.log(`[测试中] ${testName}`);
      
      const player = await this.playerService.registerPlayer(
        `stats_test_user_${Date.now()}`,
        '统计测试玩家'
      );
      
      if (!player) {
        this.addTestResult(testName, false, '注册失败，无法进行统计功能测试');
        console.log(`❌ ${testName}: 失败 - 注册失败`);
        return;
      }
      
      // 完成一些案件来生成统计数据
      await this.playerService.completeCase(
        player.id,
        'stats_case_1',
        true,
        2,
        180,
        true
      );
      
      await this.playerService.completeCase(
        player.id,
        'stats_case_2',
        false,
        1,
        120,
        true
      );
      
      await this.playerService.completeCase(
        player.id,
        'stats_case_3',
        true,
        3,
        240,
        true
      );
      
      const playerAggregate = await this.playerService.getPlayerById(player.id);
      const statistics = playerAggregate?.getStatistics();
      
      if (statistics && statistics.solvedCases === 2 && statistics.totalPlayTime > 0) {
        this.addTestResult(testName, true, '玩家统计功能测试成功');
        console.log(`✅ ${testName}: 成功`);
      } else {
        this.addTestResult(testName, false, '统计数据计算不准确');
        console.log(`❌ ${testName}: 失败 - 统计数据不准确`);
      }
    } catch (error) {
      this.addTestResult(testName, false, `统计功能测试过程发生错误: ${error}`);
      console.log(`❌ ${testName}: 失败 - ${error}`);
    }
  }
  
  // 测试排行榜功能
  private async testLeaderboard(): Promise<void> {
    const testName = '排行榜功能测试';
    try {
      console.log(`[测试中] ${testName}`);
      
      // 创建几个测试玩家
      for (let i = 0; i < 3; i++) {
        const player = await this.playerService.registerPlayer(
          `leaderboard_test_user_${Date.now()}_${i}`,
          `排行榜测试玩家${i}`
        );
        
        if (player) {
          // 不同玩家完成不同数量的案件
          for (let j = 0; j <= i; j++) {
            await this.playerService.completeCase(
              player.id,
              `leaderboard_case_${i}_${j}`,
              true,
              1,
              60,
              true
            );
          }
        }
      }
      
      // 获取排行榜
      const leaderboard = await this.playerService.getPlayerLeaderboard(10);
      
      if (leaderboard && leaderboard.length > 0) {
        // 检查排序是否正确（按解决案件数降序）
        let isCorrectlySorted = true;
        for (let i = 0; i < leaderboard.length - 1; i++) {
          if (leaderboard[i].player.solvedCases < leaderboard[i + 1].player.solvedCases) {
            isCorrectlySorted = false;
            break;
          }
        }
        
        if (isCorrectlySorted) {
          this.addTestResult(testName, true, '排行榜功能测试成功');
          console.log(`✅ ${testName}: 成功`);
        } else {
          this.addTestResult(testName, false, '排行榜排序不正确');
          console.log(`❌ ${testName}: 失败 - 排序不正确`);
        }
      } else {
        this.addTestResult(testName, false, '排行榜返回为空');
        console.log(`❌ ${testName}: 失败 - 排行榜为空`);
      }
    } catch (error) {
      this.addTestResult(testName, false, `排行榜功能测试过程发生错误: ${error}`);
      console.log(`❌ ${testName}: 失败 - ${error}`);
    }
  }
  
  private addTestResult(testName: string, success: boolean, message: string): void {
    this.testResults.push({ testName, success, message });
  }
  
  private printTestSummary(): void {
    console.log('====== 玩家模块测试结果汇总 ======');
    
    const totalTests = this.testResults.length;
    const passedTests = this.testResults.filter(result => result.success).length;
    const failedTests = totalTests - passedTests;
    
    console.log(`总测试数: ${totalTests}`);
    console.log(`通过测试: ${passedTests}`);
    console.log(`失败测试: ${failedTests}`);
    
    if (failedTests > 0) {
      console.log('\n失败的测试:');
      this.testResults
        .filter(result => !result.success)
        .forEach(result => {
          console.log(`- ${result.testName}: ${result.message}`);
        });
    }
    
    console.log('\n测试完成!');
  }
}

// 导出一个可直接调用的测试函数
export async function testPlayerModule(): Promise<void> {
  const tester = new PlayerModuleTester();
  await tester.runAllTests();
}
